#!/usr/bin/env python

from BeautifulSoup import BeautifulSoup
import random
import mechanize
import cookielib
import time
import re
import formDailiesData as fdd



class Browser:

  def __init__(self, userAgent, testMode=True):
    self.br = mechanize.Browser()

    self.cj = cookielib.LWPCookieJar()
    self.br.set_cookiejar(self.cj)

    self.br.set_handle_equiv(True)
    self.br.set_handle_redirect(True)
    self.br.set_handle_referer(True)
    self.br.set_handle_robots(False)
    self.br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)
    self.br.addheaders = [('User-agent', userAgent)]
    self.testMode = testMode

  def doLogin(self, username, password, sleepSeconds):
    self.username = username
    if not self.testMode:
      try:
        self.cj.load('%s.cj' % username)
        print 'loaded cookie!'
      except IOError as e:
        pass
      firstPage = self.doOpen('http://www.neopets.com/')
      if 'userlookup.phtml?user=%s' % (username) in repr(str(firstPage)):
        print 'used cookie to login'
        return 'Successful login'
      print 'proceeding with regular login'
      self.doSleep(sleepSeconds)
      url = 'http://www.neopets.com/login.phtml?username=%s&password=%s' % (username, password)
      resp = self.doOpen(url, 'logs/pageAfterLogin.html')
      self.saveCookie()
      if 'userlookup.phtml?user=%s' % (username) in repr(str(resp)):
        return 'Successful login'
      else:
        return 'Login Failed!'
    return 'TestMode, probably logged in'


  def saveCookie(self):
    self.cj.save('%s.cj' % self.username)


  def getSlug(self, sleepSeconds):
    data = fdd.dailyData['Slug']
    return self.getDaily2Urls( sleepSeconds, data)

  def getBobApples(self, sleepSeconds):
    data = fdd.dailyData['Bob4Apples']
    return self.getDaily2Urls( sleepSeconds, data)


  def getDaily2Urls( self, sleepSeconds, data ):
    resp = self.doOpen(data['url'])
    self.doSleep(sleepSeconds)
    if not self.testMode and ( 'phraseInForm' not in data or data['phraseInForm'] in resp):
      resp2 = self.doOpen(data['url2'])
      htmlResponse = resp2
      with open(data['fileToWrite'], 'w') as f:
        f.write(htmlResponse)
      return self.determineOutcome( data['reg'], htmlResponse )
    return 'TestMode, probly did something?'


  def getBagatelle(self, sleepSeconds, sleepSecondsArray):
    def doRequest(input, requestToSend, referer, fileToWrite):
      if not self.testMode:
        req = mechanize.Request(requestToSend[0] % (input), requestToSend[1])
        req.add_header("Referer", referer)
        self.cj.add_cookie_header(req)
        resp = self.doOpen(req, fileToWrite % (input))
        return resp
      else:
        return 'points=250&totalnp=1555&prize_id=&success=RRLL&error=So+close...' #similar to a regular response

    data = fdd.dailyData['20x Bagatelle']
    url = data['url']
    reg = data['reg']
    requestToSend = data['requestToSend']
    referer = data['referer']
    fileToWrite = data['fileToWrite']
    resp = self.doOpen(url)
    randomNums = [random.randint(1,99999) for i in range(20)]
    results = []
    self.doSleep(sleepSeconds)
    for i in randomNums:
      self.doSleep(sleepSecondsArray.pop())
      resp = doRequest(i, requestToSend, referer, fileToWrite)
      outcome = self.determineOutcome(reg, resp)
      results.append( outcome )
    return results


  def getWheelOfExcitement(self, sleepSeconds):
    return self.getDailyGenericFlash(sleepSeconds, fdd.dailyData["Wheel of Excitement"])


  def getDailyGenericFlash(self, sleepSeconds, data):
    url, referer, fileToWrite, reg, requestToSend = data['url'], data['referer'], data['fileToWrite'], data['reg'], data['requestToSend']
    resp = self.doOpen(url)
    refVal = re.findall( referer, resp )
    if len(refVal)>0 and not self.testMode:
      self.doSleep(sleepSeconds)
      req = mechanize.Request(requestToSend[0], requestToSend[1])
      req.add_header("Referer", refVal[0])
      self.cj.add_cookie_header(req)
      resp = self.doOpen(req, fileToWrite)
      strResp = re.sub(r'[^\w]','',safe_str(resp) )
      print str(strResp)
      return self.determineOutcome( reg, str(strResp) )
    return 'Test mode or no referer (program may need to be updated)'


  def countPotatoes(self, html):
    potato1 = """<img src='http://images.neopets.com/medieval/potato1"""
    potato2 = """<img src='http://images.neopets.com/medieval/potato2"""
    potato3 = """<img src='http://images.neopets.com/medieval/potato3"""
    potato4 = """<img src='http://images.neopets.com/medieval/potato4"""

    total = 0
    for line in html.split('\n'):
      if '<table align=center cellpadding=3 cellspacing=0 border=0><tr' in line:
        total+= line.count(potato1)
        total+= line.count(potato2)
        total+= line.count(potato3)
        total+= line.count(potato4)
    return str(total)



  def selectPhraseAndSubmit(self, sleepSeconds, data, submitDict=None):
    formIndex = self.findFormIndexByStr(data['phraseInForm'])
    if formIndex:
      self.doSleep(sleepSeconds)
      return self.selectAndSubmit(formIndex, data['fileToWrite'], submitDict)
    return "Couldn't find form to submit"


  def getPotatoCounter(self, sleepSeconds):
    def doGuess(sleepSeconds, html, fileToWrite, data):
      return self.selectPhraseAndSubmit(sleepSeconds, data, {'guess' : self.countPotatoes(html)} )

    data = fdd.dailyData['Potato Counter']
    resp = self.doOpen( data['url'] )
    if not self.testMode:
      retVal = []
      for i in range(3):
        resp = doGuess(sleepSeconds, resp, 'logs/potato%s.html' % i, data)
        retVal.append( self.determineOutcome( data['reg'], resp ) )
        if i != 2:
          formIndex = self.findFormIndexByStr('Play Again')
          if formIndex:
            self.doSleep( sleepSeconds)
            resp = self.selectAndSubmit(formIndex, 'logs/potatoRESP%s.html' % i)
          else: break
      return str(retVal) or "You may have already done this today"
    return "TESTMODE"


  def findFormIndexByStr(self, phraseInForm):
    for index, form in enumerate(self.br.forms()):
      if phraseInForm in str(form):
        return index
    return False


  def getDailyGenericForm(self, sleepSeconds, data):
    url, phraseInForm, fileToWrite, reg = data['url'], data['phraseInForm'], data['fileToWrite'], data['reg']
    resp = self.doOpen(url)
    if not self.testMode:
      resp = self.selectPhraseAndSubmit(sleepSeconds, data)
      return self.determineOutcome( reg, resp )
    return 'TestMode, probly did something?'


  def getGrumpyKing(self, sleepSeconds):
    data = fdd.dailyData['Grumpy King']
    resp = self.doOpen(data['url'], 'logs/grumpyb4.html')
    if not self.testMode:
      soup = BeautifulSoup(resp)
      selectionDict = {}
      for item in ['qp1', 'qp2', 'qp3', 'qp4', 'qp5', 'qp6', 'qp7', 'qp8', 'qp9', 'qp10', 'ap1', 'ap2', 'ap3', 'ap4', 'ap5', 'ap6', 'ap7', 'ap8']:
        qp1 = soup.findAll('select', attrs={'name' : item} )
        l = [option.attrs[0][1] for option in qp1[0].findAll('option')]
        selection = ' '
#          while ' ' in selection or ',' in selection or '-' in selection:
        selection = l[random.randint(1,len(l)-1)]
        selectionDict[item] = [selection]

      resp2 = self.selectPhraseAndSubmit(sleepSeconds*3, data, selectionDict)
      return self.determineOutcome( data['reg'], resp2)
    return "Test mode, probably did something"


  def determineOutcome(self, reg, htmlResponse):
    for outcome, reg in reg:
      if re.findall( reg, htmlResponse):
        return str(re.findall( reg, htmlResponse))
    if htmlResponse == "Couldn't find form to submit":
      return htmlResponse
    if """Enter your username in the box below and we will send your password to your account's email address.""" in htmlResponse:
      return "Got logged out"


  def selectAndSubmit(self, index, fileToWrite, submitDict = None):
    self.br.select_form(nr=index)
    if submitDict:
      for key in submitDict:
        self.br[key] = submitDict[key]
    resp = self.br.submit()
    htmlResponse = resp.read()
    with open(fileToWrite, 'w') as f:
      f.write(htmlResponse)
    return htmlResponse


  def getJelly(self, sleepSeconds):
    return self.getDailyGenericForm( sleepSeconds, fdd.dailyData['Jelly'])

  def getOmelette(self, sleepSeconds):
    return self.getDailyGenericForm( sleepSeconds, fdd.dailyData['Omelette'])

  def getAnchor(self, sleepSeconds):
    return self.getDailyGenericForm( sleepSeconds, fdd.dailyData['Anchor'] )

  def getShrine(self, sleepSeconds):
    return self.getDailyGenericForm( sleepSeconds, fdd.dailyData['Shrine'] )

  def getBankInterest(self, sleepSeconds):
    return self.getDailyGenericForm( sleepSeconds, fdd.dailyData['Bank Interest'] )

  def getIceScratchCard(self, sleepSeconds):
    return self.getDailyGenericForm( sleepSeconds, fdd.dailyData['Ice Scratch Card'] )

  def getDesertScratchCard(self, sleepseconds):
    return self.getDailyGenericForm( sleepseconds, fdd.dailyData['Desert Scratch Card'] )

  def getHalloweenScratchCard(self, sleepSeconds):
    return self.getDailyGenericForm( sleepSeconds, fdd.dailyData['Halloween Scratch Card'] )

  def getFruitMachine(self, sleepSeconds):
    return self.getDailyGenericForm( sleepSeconds, fdd.dailyData['Fruit Machine'] )

  def getPlushieOfProsperity(self, sleepSeconds):
    return self.getDailyGenericForm( sleepSeconds, fdd.dailyData['Plushie Of Prosperity'] )

  def getFishing(self, sleepSeconds):
    return self.getDailyGenericForm( sleepSeconds, fdd.dailyData['Fishing'] )

  def getTombola(self, sleepSeconds):
    return self.getDailyGenericForm( sleepSeconds, fdd.dailyData['Tombola'] )

  def getHealingSprings(self, sleepSeconds):
    return self.getDailyGenericForm( sleepSeconds, fdd.dailyData['Healing Springs'] )


  def doOpen(self, url, fileToWrite=None):
    if not self.testMode:
      response = self.br.open( url )
      htmlResponse = response.read()
      if fileToWrite:
        writeToFile(htmlResponse, fileToWrite)
      self.saveCookie()
      return htmlResponse
    return 'testresponse'


  def doSleep(self, seconds):
    if not self.testMode:
      time.sleep(seconds)


def safe_str(obj):
  try:
    return str(obj)
  except UnicodeEncodeError:
    return unicode(obj).encode('unicode_escape')

def writeToFile(stuffToWrite, filename):
  with open(filename, 'w') as f:
    f.write(stuffToWrite)

# Download a FILE!
#f = br.retrieve('http://www.google.com.br/intl/pt-BR_br/images/logo.gif')[0]
#print f
#fh = open(f)
